using System.Windows;
using System.Windows.Controls;
using Bookvar.ObjectModel;

namespace Bookvar.UI.Arrangers
{
    public abstract class TopicArranger
    {
        private readonly MindMapPanel panel;

        protected TopicArranger( MindMapPanel panel )
        {
            this.panel = panel;
        }

        protected virtual void BalanceMap( TopicContentPresenter presenter )
        {
        }

        public void BalanceMap()
        {
            //HACK: using this to apply animation, refactor at any cost
            MindMapPanel.OnTopicArrangerPropertyChanged( panel, new DependencyPropertyChangedEventArgs() );

            BalanceMap( panel.MainTopicPresenter );
        }

        // This is internal so MindMapPanel can arrange only the MainTopic. This is necessary for backword
        // compatibility when opening old maps, that did not have MainTopic position saved.
        protected internal abstract void ArrangeMainTopic( TopicContentPresenter mainTopicPresenter, Size size );

        protected virtual void ArrangeChildTopics( TopicContentPresenter parentPresenter )
        {
            if ( parentPresenter.Children.Count > 0 )
            {
                foreach ( TopicContentPresenter child in parentPresenter.Children )
                {
                    ArrangeChildTopics( child );
                }
            }
        }

        public void ArrangeMindmap( TopicContentPresenter presenter, Size size )
        {
            if ( presenter.Topic is MainTopic )
            {
                ArrangeMainTopic( presenter, size );
            }
            ArrangeChildTopics( presenter );
        }

        #region Position Helpers

        protected static void SetLeft( UIElement presenter, double value )
        {
            double left = GetLeft( presenter );
            if ( left != value )
            {
                Canvas.SetLeft( presenter, value );
            }
        }

        protected static double GetLeft( UIElement element )
        {
            double left = Canvas.GetLeft( element );
            return double.IsNaN( left ) ? 0 : left;
        }

        protected static void SetTop( UIElement presenter, double value )
        {
            double top = GetTop( presenter );
            if ( top != value )
            {
                Canvas.SetTop( presenter, value );
            }
        }

        protected static double GetTop( UIElement element )
        {
            double top = Canvas.GetTop( element );
            return double.IsNaN( top ) ? 0 : top;
        }

        #endregion
    }
}